package com.mlx.mbg.code.method;

import com.mlx.mbg.code.MbgUtil;
import com.mlx.mbg.code.inter.EnableMethod;
import com.mlx.mbg.code.config.MbgPropertyConfig;
import com.mlx.mbg.code.inter.ExtensionLevel;
import com.mlx.mbg.code.inter.IExtensionMethod;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.xml.Attribute;
import org.mybatis.generator.api.dom.xml.TextElement;
import org.mybatis.generator.api.dom.xml.XmlElement;

import java.util.ArrayList;
import java.util.List;

@EnableMethod
public class SelectOneMethod implements IExtensionMethod {
    @Override
    public boolean checkConfig(ExtensionLevel level, MbgPropertyConfig mbgPropertyConfig, IntrospectedTable introspectedTable) {
        return getExtensionLevelSet().contains(level) && mbgPropertyConfig.getEnableSelectOne() && MbgUtil.checkInterfaceExpressionFormat(introspectedTable, "单条查询", "selectOne");
    }

    @Override
    public int getOrder() {
        return 1300;
    }

    @Override
    public List<Method> buildMethod(IntrospectedTable introspectedTable) {
        List<Method> methodList = new ArrayList<>();
        String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();
        String uniqueKeysString = introspectedTable.getTableConfigurationProperty("selectOne");

        String[] uniqueKeys = uniqueKeysString.split(";");

        for (String uniqueKey : uniqueKeys){
            String[] keys = uniqueKey.split(",");
            List<IntrospectedColumn> keyColumnList = new ArrayList<IntrospectedColumn>();
            for (String key : keys){
                IntrospectedColumn column = introspectedTable.getColumn(key);
                keyColumnList.add(column);
            }

            JavaVisibility methodVisibility = JavaVisibility.PUBLIC;

            // 设置返回类型：实体类类型
            FullyQualifiedJavaType methodReturnType = new FullyQualifiedJavaType(introspectedTable.getBaseRecordType());

            StringBuilder methodName = new StringBuilder("getBy");
            StringBuilder remarkItem = new StringBuilder();
            for (IntrospectedColumn column : keyColumnList){

                String javaProperty = column.getJavaProperty();
                remarkItem.append(javaProperty).append(",");

                String substring0 = javaProperty.substring(0, 1);
                String substring1 = javaProperty.substring(1);
                String javaPropertyUp0 = substring0.toUpperCase() + substring1;
                methodName.append(javaPropertyUp0);
            }
            remarkItem.deleteCharAt(remarkItem.length() - 1);

            List<Parameter> methodParameterList = new ArrayList<Parameter>();
            for (IntrospectedColumn column : keyColumnList){

                String javaProperty = column.getJavaProperty();

                FullyQualifiedJavaType javaType = column.getFullyQualifiedJavaType();

                // 参数类型
                FullyQualifiedJavaType methodParameterType = new FullyQualifiedJavaType(javaType.getShortName());

                // 方法参数
                Parameter methodParameter = new Parameter(methodParameterType, javaProperty);

                methodParameterList.add(methodParameter);

            }

            Method method = new Method();
            method.setVisibility(methodVisibility);
            method.setReturnType(methodReturnType);
            method.setName(methodName.toString());
            for (Parameter parameter : methodParameterList){
                method.addParameter(parameter);
            }
            method.addJavaDocLine("/**");
            method.addJavaDocLine(" * 唯一索引查询：通过" + remarkItem + "查询");
            method.addJavaDocLine(" */");

            methodList.add(method);
        }

        return methodList;
    }

    @Override
    public List<XmlElement> buildSQL(IntrospectedTable introspectedTable) {
        List<XmlElement> elementList = new ArrayList<>();
        String tableName = introspectedTable.getAliasedFullyQualifiedTableNameAtRuntime();
        String uniqueKeysString = introspectedTable.getTableConfigurationProperty("selectOne");

        String[] uniqueKeys = uniqueKeysString.split(";");

        for (String uniqueKey : uniqueKeys){
            String[] keys = uniqueKey.split(",");
            List<IntrospectedColumn> keyColumnList = new ArrayList<IntrospectedColumn>();
            for (String key : keys){
                IntrospectedColumn column = introspectedTable.getColumn(key);
                keyColumnList.add(column);
            }

            XmlElement where = new XmlElement("where");
            StringBuilder methodName = new StringBuilder("getBy");
            StringBuilder remarkItem = new StringBuilder();
            for (IntrospectedColumn column : keyColumnList){
                String actualColumnName = column.getActualColumnName();
                String jdbcTypeName = column.getJdbcTypeName();
                String javaProperty = column.getJavaProperty();
                remarkItem.append(javaProperty).append(",");

                String substring0 = javaProperty.substring(0, 1);
                String substring1 = javaProperty.substring(1);
                String javaPropertyUp0 = substring0.toUpperCase() + substring1;
                methodName.append(javaPropertyUp0);

                TextElement text = new TextElement("and " + actualColumnName + " = #{" + javaProperty + ",jdbcType=" + jdbcTypeName + "}");
                where.addElement(text);
            }
            remarkItem.deleteCharAt(remarkItem.length() - 1);

            XmlElement method = new XmlElement("select");
            method.addAttribute(new Attribute("id", methodName.toString()));
            method.addAttribute(new Attribute("resultMap", "BaseResultMap"));
            TextElement text3 = new TextElement("select");
            XmlElement baseInclude = new XmlElement("include");
            baseInclude.addAttribute(new Attribute("refid", "Base_Column_List"));
            TextElement text4 = new TextElement("from " + introspectedTable.getFullyQualifiedTableNameAtRuntime());
            method.addElement(text3);
            method.addElement(baseInclude);
            method.addElement(text4);
            method.addElement(where);

            elementList.add(method);

        }

        return elementList;
    }
}
